package org.elsfs.cloud.common.mybatis.ext.sql;

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import org.apache.commons.compress.utils.Lists;
import org.elsfs.cloud.common.core.entity.BaseEntity;
import org.elsfs.cloud.common.mybatis.ext.sql.support.delete.CompositeDeleteItem;
import org.elsfs.cloud.common.mybatis.ext.sql.support.delete.DeleteItem;
import org.elsfs.cloud.common.mybatis.ext.sql.support.delete.StandardDeleteItem;
import org.elsfs.cloud.common.mybatis.ext.sql.support.from.FromItem;
import org.elsfs.cloud.common.mybatis.ext.sql.support.from.StandardFromItem;

import java.util.Collection;

/**
 * 抽象删除SQL实现
 *
 * @param <C> 子类具体类型
 */
public abstract class AbstractDeleteSql<C extends AbstractDeleteSql<C>> extends AbstractJoin<C> implements DeleteSql<C, AbstractDeleteSql<C>.DeleteConditionBuilderImpl> {

    /**
     * 具体子类实现引用
     */
    protected final C childThis = (C)  this;

    /**
     * 删除条件构建器
     */
    private DeleteConditionBuilderImpl deleteConditionBuilder;
    /**
     * 删除From项
     */
    private FromItem fromItem;
    /**
     * 删除项集合
     */
    private final Collection<DeleteItem> deleteItems = Lists.newArrayList();

    /**
     * 删除数据的表别名
     *
     * @param tableAlias 表别名
     * @return 具体实现
     */
    @Override
    public C delete(String tableAlias) {
        this.deleteItems.add(
            new StandardDeleteItem(tableAlias)
        );

        return this.childThis;
    }

    /**
     * 删除数据的表别名
     *
     * @param tableAliases 表别名
     * @return 具体实现
     */
    @Override
    public C delete(String... tableAliases) {
        for (String tableAlias : tableAliases) {
            this.deleteItems.add(
                new StandardDeleteItem(tableAlias)
            );
        }

        return this.childThis;
    }

    /**
     * 删除数据的表别名
     *
     * @param tableAliases 表别名
     * @return 具体实现
     */
    @Override
    public C delete(Collection<String> tableAliases) {
        for (String tableAlias : tableAliases) {
            this.deleteItems.add(
                new StandardDeleteItem(tableAlias)
            );
        }

        return this.childThis;
    }

    /**
     * 设置删除数据的表
     *
     * @param entityClass 实体类
     * @return 具体实现
     */
    @Override
    public C from(Class<? extends BaseEntity> entityClass) {
        this.fromItem = new StandardFromItem(
            TableInfoHelper.getTableInfo(entityClass).getTableName(),
            null
        );

        return this.childThis;
    }

    /**
     * 设置删除数据的表
     *
     * @param table 表名
     * @return 具体实现
     */
    @Override
    public C from(String table) {
        this.fromItem = new StandardFromItem(
            table,
            null
        );

        return this.childThis;
    }

    /**
     * 设置删除数据的表
     *
     * @param entityClass 实体类
     * @param tableAlias  表别名
     * @return 具体实现
     */
    @Override
    public C from(Class<? extends BaseEntity> entityClass, String tableAlias) {
        this.fromItem = new StandardFromItem(
            TableInfoHelper.getTableInfo(entityClass).getTableName(),
            tableAlias
        );

        return this.childThis;
    }

    /**
     * 设置删除数据的表
     *
     * @param table      表名
     * @param tableAlias 表别名
     * @return 具体实现
     */
    @Override
    public C from(String table, String tableAlias) {
        this.fromItem = new StandardFromItem(
            table,
            tableAlias
        );

        return this.childThis;
    }

    /**
     * 删除条件设置
     *
     * @return 条件构建器
     */
    @Override
    public DeleteConditionBuilder<DeleteConditionBuilderImpl, C> where() {
        if (this.deleteConditionBuilder == null) {
            this.deleteConditionBuilder = new DeleteConditionBuilderImpl();
        }

        return this.deleteConditionBuilder;
    }

    /**
     * 构建SQL之前处理
     */
    @Override
    protected void beforeBuild() {
        this.addSqlFragment(
            new TokenSqlFragment("DELETE")
        );
        if (!this.deleteItems.isEmpty()) {
            this.addSqlFragment(
                new CompositeDeleteItem(this.deleteItems)
            );
        }
        if (this.fromItem == null) {
            throw new MybatisPlusException( "删除SQL的表必须指定");
        }
        this.addSqlFragment(
            this.fromItem
        );
        super.beforeBuild();
        if (this.deleteConditionBuilder != null) {
            this.addSqlFragment(this.deleteConditionBuilder);
        }
    }

    /**
     * 删除条件构建器
     */
    public class DeleteConditionBuilderImpl extends AbstractSortableConditionBuilder<DeleteConditionBuilderImpl> implements DeleteConditionBuilder<DeleteConditionBuilderImpl, C> {

        /**
         * 返回上一级对象
         *
         * @return 上级对象
         */
        @Override
        public C end() {
            return AbstractDeleteSql.this.childThis;
        }

        /**
         * 获取SQL参数管理器
         *
         * @return SQL参数管理器
         */
        @Override
        public SqlParameterManager getSqlParameterManager() {
            return AbstractDeleteSql.this.getSqlParameterManager();
        }

        /**
         * 获取表别名管理器
         *
         * @return 表名别管理器
         */
        @Override
        public TableAliasManager getTableAliasManager() {
            return AbstractDeleteSql.this.getTableAliasManager();
        }
    }
}
